﻿// 课程设计(哈夫曼编译码器)-梁俊华.cpp : 定义应用程序的入口点。
//

#include "framework.h"
#include "课程设计(哈夫曼编译码器)-梁俊华.h"

#pragma warning(disable:26400)	//请勿将包含owner<T>返还值的分配或调用结果分配给原始指针
#pragma warning(disable:26401)	//请勿删除不是owner<T>的原始指针
#pragma warning(disable:26409)	//避免显式调用new和delete
#pragma warning(disable:26432)	//如果定义或删除类型class Hfm 中的任何默认操作，请全部定义或删除它们
#pragma warning(disable:26446)	//优先使用gsl::at()而非选中下标运算符
#pragma warning(disable:26481)	//请勿使用指针算法
#pragma warning(disable:26482)	//只使用常量表达式在数组编制索引
#pragma warning(disable:26493)	//请勿使用C样式转换
#pragma warning(disable:26492)	//请勿使用const_cast

#define MAX_LOADSTRING 100
#define EDITTEXTMAXLEN 30000
#define FILEMAXLEN 128

// 全局变量:
HINSTANCE hInst;                                // 当前实例
WCHAR szTitle[MAX_LOADSTRING];                  // 标题栏文本
WCHAR szWindowClass[MAX_LOADSTRING];            // 主窗口类名
HWND WindowHwnd = NULL;                         //主窗口句柄

// 此代码模块中包含的函数的前向声明:
ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK ChildProc(HWND hWndChild, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData);

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    // TODO: 在此处放置代码。

    // 初始化全局字符串
    LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadStringW(hInstance, IDC_WINDOWCLASS, szWindowClass, MAX_LOADSTRING);
    MyRegisterClass(hInstance);

    // 执行应用程序初始化:
    if (!InitInstance (hInstance, nCmdShow))
    {
        return FALSE;
    }

    HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_MENU_ACCELERATION_KEY));

    MSG msg;

    // 主消息循环:
    while (GetMessage(&msg, nullptr, 0, 0))
    {
        if (!TranslateAccelerator(WindowHwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return (int) msg.wParam;
}



//
//  函数: MyRegisterClass()
//
//  目标: 注册窗口类。
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEXW wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style          = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = WndProc;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;
    wcex.hInstance      = hInstance;
    wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDC_WINDOWCLASS));
    wcex.hCursor        = LoadCursor(nullptr, IDC_ARROW);
    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName   = MAKEINTRESOURCEW(IDC_MENU);
    wcex.lpszClassName  = szWindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLOGO));

    return RegisterClassExW(&wcex);
}

//
//   函数: InitInstance(HINSTANCE, int)
//
//   目标: 保存实例句柄并创建主窗口
//
//   注释:
//
//        在此函数中，我们在全局变量中保存实例句柄并
//        创建和显示主程序窗口。
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   hInst = hInstance; // 将实例句柄存储在全局变量中

   HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);

   if (!hWnd)
   {
      return FALSE;
   }
   WindowHwnd = hWnd;

   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}

//
//  函数: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  目标: 处理主窗口的消息。
//
//  WM_COMMAND  - 处理应用程序菜单
//  WM_PAINT    - 绘制主窗口
//  WM_DESTROY  - 发送退出消息并返回
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    static RECT     WindowRect = { 0 };                    //窗口宽度
    static LONG     controlWidth = 0;                      //控件宽度
    static LONG     controlHeight = 0;                     //控件高度
    static HWND     hwnd[5] = {nullptr};                   //子窗口句柄
    static FILE* fp = NULL;                                //控制台文件地址
    OPENFILENAME ofn = { 0 };                              //打开保存对话框信息结构
    TCHAR szFile[FILEMAXLEN] = TEXT("");                   //文件名字符串数组地址
    TCHAR szFileTitle[FILEMAXLEN] = TEXT("");              //文件名和扩展名字符串数组地址

    ofn.nFilterIndex = 1;
    ofn.hwndOwner = hWnd;
    ofn.lpstrFile = szFile;
    ofn.lpstrFile[0] = NULL;
    ofn.lStructSize = sizeof(ofn);
    ofn.nMaxFile = _countof(szFile);
    ofn.lpstrFileTitle = szFileTitle;
    ofn.lpstrInitialDir = TEXT("C:\\");
    ofn.nMaxFileTitle = _countof(szFileTitle);

    switch (message)
    {
    case WM_CREATE:
        //获取客户区矩形
        GetClientRect(hWnd, &WindowRect);
        //计算控件宽高
        controlWidth = (WindowRect.right - 50) / 3;
        controlHeight = WindowRect.bottom - 30;
        //创建控件
        hwnd[0] = CreateWindowEx(0, TEXT("Button"), TEXT("开始编码"),
            WS_CHILD | WS_VISIBLE | WS_DLGFRAME | WS_TABSTOP | BS_DEFPUSHBUTTON | BS_NOTIFY,
            15, 10, controlWidth / 2 - 5, 60, hWnd, (HMENU)IDC_STARTCODE, hInst, NULL);
        hwnd[1] = CreateWindowEx(0, TEXT("Button"), TEXT("清空"),
            WS_CHILD | WS_VISIBLE | WS_DLGFRAME | WS_TABSTOP | BS_DEFPUSHBUTTON | BS_NOTIFY,
            15 + controlWidth / 2 + 5, 10, controlWidth / 2 - 5, 60, hWnd, (HMENU)IDC_CLEAR, hInst, NULL);
        hwnd[2] = CreateWindowEx(0, TEXT("Edit"), NULL,
            WS_CHILD | WS_VISIBLE | WS_DLGFRAME | WS_VSCROLL | ES_MULTILINE | ES_AUTOVSCROLL,
            15, 80, controlWidth, controlHeight - 80, hWnd, (HMENU)(IDC_DECOING), hInst, NULL);
        hwnd[3] = CreateWindowEx(0, TEXT("Edit"), NULL,
            WS_CHILD | WS_VISIBLE | WS_DLGFRAME | WS_VSCROLL | ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY,
            25 + controlWidth, 10, controlWidth, controlHeight, hWnd, (HMENU)(IDC_MEDIAN_VALUE), hInst, NULL);
        hwnd[4] = CreateWindowEx(0, TEXT("Edit"), NULL,
            WS_CHILD | WS_VISIBLE | WS_DLGFRAME | WS_VSCROLL | ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY,
            35 +  2 * controlWidth, 10, controlWidth, controlHeight, hWnd, (HMENU)(IDC_CODE), hInst, NULL);
        //控件子类化
        for (UINT i = 0; i < 5; i++) {
            SetWindowSubclass(hwnd[i], ChildProc, IDW_CHILD, 0);
        }
        //设置控件字体
        SendMessage(hWnd, WM_SETFONT, (WPARAM)CreateFont(28, 0, 0, 0, 400, 0, 0, 0, GB2312_CHARSET, 0, 0, 0, 0, TEXT("宋体")), (LPARAM)TRUE);
        for (UINT i = 0; i < 5; i++) {
            SendMessage(hwnd[i], WM_SETFONT, (WPARAM)CreateFont(18, 0, 0, 0, 400, 0, 0, 0, GB2312_CHARSET, 0, 0, 0, 0, TEXT("宋体")), (LPARAM)TRUE);
        }
        //设置编辑控件最大字符数
        for (UINT i = 2; i < 5; i++) {
            SendMessage(hwnd[i], EM_SETLIMITTEXT, EDITTEXTMAXLEN, 0);
        }
        break;

    case WM_SIZE:
        //获取客户区矩形
        GetClientRect(hWnd, &WindowRect);
        //计算控件宽高
        controlWidth = (WindowRect.right - 50) / 3;
        controlHeight = WindowRect.bottom - 30;
        //修改窗口大小
        MoveWindow(hwnd[0], 15, 10, controlWidth / 2 - 5, 60, TRUE);
        MoveWindow(hwnd[1], 15 + controlWidth / 2 + 5, 10, controlWidth / 2 - 5, 60, TRUE);
        MoveWindow(hwnd[2], 15, 80, controlWidth, controlHeight - 80, TRUE);
        MoveWindow(hwnd[3], 25 + controlWidth, 10, controlWidth, controlHeight, TRUE);
        MoveWindow(hwnd[4], 35 + 2 * controlWidth, 10, controlWidth, controlHeight, TRUE);
        break;

    case WM_GETMINMAXINFO:
        ((MINMAXINFO*)lParam)->ptMinTrackSize.x = 600;
        break;

    case WM_COMMAND:
        {
            int wmId = LOWORD(wParam);
            // 分析菜单选择:
            switch (wmId)
            {
            case ID_OPEN_CODE_FILE:    //打开编码文件菜单
                if (TRUE) {
                    TCHAR const* decoding = NULL;
                    Hfm::BOOL* code = NULL;
                    Hfm::HFMTREE* hfmTree = NULL;
                    Hfm::HFMCHARACTERCODE const* hfmCharacterCode = NULL;
                    LPTSTR  codeStr = NULL, hfmTreeStr = NULL, hfmCharacterCodeStr = NULL, medianValue = NULL;
                    size_t decodingLength = 0, codeLength = 0, hfmTreeLength = 0, hfmCharacterCodeLength = 0, medianValueLength = 0;
                    try {
                        ofn.lpstrTitle = TEXT("打开文件");
                        ofn.lpstrDefExt = TEXT("");
                        ofn.lpstrFilter = TEXT("二进制文件(*.bin)\0*.bin\0");
                        ofn.Flags = OFN_EXPLORER;
                        if (GetOpenFileName(&ofn)) {
                            //读取文件数据
                            TargetWork targetWork;
                            if (!targetWork.ReadCodeFile(ofn.lpstrFile, &hfmTree, &hfmTreeLength, &code, &codeLength)) {
                                MessageBox(hWnd, TEXT("数据读取失败"), TEXT("错误"), MB_OK | MB_ICONERROR);
                            }
                            //译码
                            Hfm hfm(hfmTree, hfmTreeLength, code, codeLength);
                            decoding = hfm.GetDecoding(&decodingLength);
                            hfmCharacterCode = hfm.GetHfmCharacterCode(&hfmCharacterCodeLength);
                            //转字符串
                            codeStr = targetWork.CodeToString(code, codeLength);
                            hfmTreeStr = targetWork.HfmTreeFormat(hfmTree, hfmTreeLength);
                            hfmCharacterCodeStr = targetWork.HfmCharacterCodeFormat(const_cast<Hfm::LPHFMCHARACTERCODE>(hfmCharacterCode), hfmCharacterCodeLength);
                            //拼接字符串
                            medianValueLength = _tcslen(hfmTreeStr) + _tcslen(hfmCharacterCodeStr) + 3;
                            medianValue = new TCHAR[medianValueLength];
                            memset(medianValue, 0, sizeof(TCHAR) * medianValueLength);
                            StringCchCat(medianValue, medianValueLength, hfmTreeStr);
                            StringCchCat(medianValue, medianValueLength, hfmCharacterCodeStr);
                            //输出到编辑框
                            SetDlgItemText(hWnd, IDC_DECOING, const_cast<LPTSTR>(decoding));
                            SetDlgItemText(hWnd, IDC_MEDIAN_VALUE, medianValue);
                            SetDlgItemText(hWnd, IDC_CODE, codeStr);
                            if (fp) {
                                //输出到控制台
                                LPSTR str = NULL;
                                targetWork.WcharToChar(const_cast<LPWSTR>(decoding), &str);
                                cout << "译文:\r\n" << str << endl;
                                targetWork.WcharToChar(medianValue, &str);
                                cout << str << endl;
                                targetWork.WcharToChar(codeStr, &str);
                                cout << "编码:\r\n" << str << endl;
                                cout << "译码成功\r\n" << str << endl;
                            }
                            //释放空间
                            delete[] medianValue;
                        }
                    }
                    catch (std::exception err) {
                        //释放空间
                        delete[] medianValue;
                        cout << err.what() << endl;
                        MessageBoxA(hWnd, err.what(), "错误", MB_OK | MB_ICONERROR);
                    }
                }
                break;

            case ID_OPEN_DECOINF_FILE:    //打开译码文件菜单
                if (TRUE) {
                    LPTSTR decoding = NULL;
                    size_t decodingLength = 0;
                    try {
                        ofn.lpstrTitle = TEXT("打开文件");
                        ofn.lpstrDefExt = TEXT("");
                        ofn.lpstrFilter = TEXT("文本文件(*.txt)\0*.txt\0");
                        ofn.Flags = OFN_EXPLORER;
                        if (GetOpenFileName(&ofn)) {
                            //读取文件数据
                            TargetWork targetWork;
                            if (!targetWork.ReadDecoingFile(ofn.lpstrFile, &decoding)) {
                                MessageBox(hWnd, TEXT("数据读取失败"), TEXT("错误"), MB_OK | MB_ICONERROR);
                            }
                            //输出到编辑框
                            SetDlgItemText(hWnd, IDC_DECOING, decoding);
                            //发送开始编码消息
                            SendMessage(hWnd, WM_COMMAND, MAKEWPARAM(IDC_STARTCODE, BN_CLICKED), (LPARAM)GetDlgItem(hWnd, IDC_DECOING));
                        }
                    }
                    catch (std::exception err) {
                        cout << err.what() << endl;
                        MessageBoxA(hWnd, err.what(), "错误", MB_OK | MB_ICONERROR);
                    }
                }
                break;

            case ID_SAVE_CODE_FILE: //保存编码文件菜单
                if (TRUE) {
                    LPTSTR decoding = NULL;
                    Hfm::BOOL const* code = NULL;
                    Hfm::HFMTREE const* hfmTree = NULL;
                    size_t decodingLength = 0, codeLength = 0, hfmTreeLength = 0;
                    try {
                        ofn.lpstrTitle = TEXT("保存为");
                        ofn.lpstrDefExt = TEXT("bin\0");
                        ofn.lpstrFilter = TEXT("二进制文件(*.bin)\0*.bin\0");
                        ofn.Flags = OFN_EXPLORER | OFN_OVERWRITEPROMPT;
                        if (GetSaveFileName(&ofn)) {
                            if (!StrRStrI(ofn.lpstrFile, NULL, TEXT(".bin"))) {
                                StringCchCat(ofn.lpstrFile, FILEMAXLEN, TEXT(".bin"));
                            }
                            //获取编辑框文本
                            if ((decodingLength = SendMessage(hwnd[2], WM_GETTEXTLENGTH, 0, 0) + 1) <= 1 || SendMessage(hwnd[4], WM_GETTEXTLENGTH, 0, 0) <= 0) {
                                MessageBox(hWnd, TEXT("无编码数据"), TEXT("提示"), MB_OK | MB_ICONASTERISK);
                                break;
                            }
                            decoding = new TCHAR[decodingLength];
                            GetDlgItemText(hWnd, IDC_DECOING, decoding, decodingLength);
                            //编码
                            Hfm hfm(decoding, decodingLength);
                            code = hfm.GetCode(&codeLength);
                            hfmTree = hfm.GetHfmTree(&hfmTreeLength);
                            //保存编码文件
                            TargetWork targetWork;
                            if (!targetWork.WriteCodeFile(ofn.lpstrFile, const_cast<Hfm::LPHFMTREE>(hfmTree), hfmTreeLength, const_cast<Hfm::BOOL*>(code), codeLength)) {
                                cout << "保存失败" << endl;
                                MessageBox(hWnd, TEXT("保存失败"), TEXT("错误"), MB_OK | MB_ICONERROR);
                            }
                            else {
                                cout << "保存成功" << endl;
                                MessageBox(hWnd, TEXT("保存成功"), TEXT("提示"), MB_OK | MB_ICONASTERISK);
                            }
                            //释放空间
                            delete[] decoding;
                        }
                    }
                    catch (std::exception err) {
                        //释放空间
                        delete[] decoding;
                        cout << err.what() << endl;
                        MessageBoxA(hWnd, err.what(), "错误", MB_OK | MB_ICONERROR);
                    }
                }
                break;

            case ID_SAVE_DECOING_FILE:  //保存译码文件菜单
                if (TRUE) {
                    LPTSTR decoding = NULL;
                    size_t decodingLength = 0;
                    try {
                        ofn.lpstrTitle = TEXT("保存为");
                        ofn.lpstrDefExt = TEXT("txt\0");
                        ofn.lpstrFilter = TEXT("文本文件(*.txt)\0*.txt\0");
                        ofn.Flags = OFN_EXPLORER | OFN_OVERWRITEPROMPT;
                        if (GetSaveFileName(&ofn)) {
                            if (!StrRStrI(ofn.lpstrFile, NULL, TEXT(".txt"))) {
                                StringCchCat(ofn.lpstrFile, FILEMAXLEN, TEXT(".txt"));
                            }
                            //获取编辑框文本
                            if ((decodingLength = SendMessage(hwnd[2], WM_GETTEXTLENGTH, 0, 0) + 1) <= 1) {
                                MessageBox(hWnd, TEXT("无译码数据"), TEXT("提示"), MB_OK | MB_ICONASTERISK);
                                break;
                            }
                            decoding = new TCHAR[decodingLength];
                            GetDlgItemText(hWnd, IDC_DECOING, decoding, decodingLength);
                            //保存译码文件
                            TargetWork targetWork;
                            if (!targetWork.WriteDecoingFile(ofn.lpstrFile, decoding)) {
                                cout << "保存失败" << endl;
                                MessageBox(hWnd, TEXT("保存失败"), TEXT("错误"), MB_OK | MB_ICONERROR);
                            }
                            else {
                                cout << "保存成功" << endl;
                                MessageBox(hWnd, TEXT("保存成功"), TEXT("提示"), MB_OK | MB_ICONASTERISK);
                            }
                            //释放空间
                            delete[] decoding;
                        }
                    }
                    catch (std::exception err) {
                        //释放空间
                        delete[] decoding;
                        cout << err.what() << endl;
                        MessageBoxA(NULL, err.what(), "错误", MB_OK | MB_ICONERROR);
                    }
                }
                break;

            case ID_EXIT:   //退出菜单
                DestroyWindow(hWnd);
                break;

            case ID_OPEN_THE_CONSOLE:   //打开控制台菜单
                AllocConsole();
                freopen_s(&fp, "conout$", "w", stdout);
                break;

            case ID_CLOSE_THE_CONSOLE:  //关闭控制台菜单
                FreeConsole();
                fclose(stdout);
                fp = NULL;
                break;

            case ID_HELP_DOCUMENTATION: //帮助文档菜单
                ShellExecute(hWnd, TEXT("open"), TEXT("help.html"), NULL, NULL, SW_SHOWMAXIMIZED);
                break;

            case ID_ABOUT:  //关于菜单
                DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
                break;

            case IDC_STARTCODE: //开始编码数按钮
                if (HIWORD(wParam) == BN_CLICKED) { //单击按钮
                    Hfm::BOOL const* code = NULL;
                    Hfm::HFMTREE const* hfmTree = NULL;
                    Hfm::HFMCHARACTERCODE const* hfmCharacterCode = NULL;
                    LPTSTR decoding = NULL, codeStr = NULL, hfmTreeStr = NULL, hfmCharacterCodeStr = NULL, medianValue = NULL;
                    size_t decodingLength = 0, codeLength = 0, hfmTreeLength, hfmCharacterCodeLength = 0, medianValueLength = 0;
                    try {
                        //获取编辑框文本
                        if ((decodingLength = SendMessage(hwnd[2], WM_GETTEXTLENGTH, 0, 0) + 1) <= 1) {
                            break;
                        }
                        decoding = new TCHAR[decodingLength];
                        GetDlgItemText(hWnd, IDC_DECOING, decoding, decodingLength);
                        //编码
                        Hfm hfm(decoding, decodingLength);
                        code = hfm.GetCode(&codeLength);
                        hfmTree = hfm.GetHfmTree(&hfmTreeLength);
                        hfmCharacterCode = hfm.GetHfmCharacterCode(&hfmCharacterCodeLength);
                        //转字符串
                        TargetWork targetWork;
                        codeStr = targetWork.CodeToString(const_cast<Hfm::BOOL*>(code), codeLength);
                        hfmTreeStr = targetWork.HfmTreeFormat(const_cast<Hfm::HFMTREE*>(hfmTree), hfmTreeLength);
                        hfmCharacterCodeStr = targetWork.HfmCharacterCodeFormat(const_cast<Hfm::HFMCHARACTERCODE*>(hfmCharacterCode), hfmCharacterCodeLength);
                        //拼接字符串
                        medianValueLength = _tcslen(hfmTreeStr) + _tcslen(hfmCharacterCodeStr) + 1;
                        medianValue = new TCHAR[medianValueLength];
                        memset(medianValue, 0, sizeof(TCHAR) * medianValueLength);
                        StringCchCat(medianValue, medianValueLength, hfmTreeStr);
                        StringCchCat(medianValue, medianValueLength, hfmCharacterCodeStr);
                        //输出到编辑框
                        SetDlgItemText(hWnd, IDC_MEDIAN_VALUE, medianValue);
                        SetDlgItemText(hWnd, IDC_CODE, codeStr);
                        if (fp) {
                            //输出到控制台
                            LPSTR str = NULL;
                            targetWork.WcharToChar(decoding, &str);
                            cout << "译文:\r\n" << str << endl;
                            targetWork.WcharToChar(medianValue, &str);
                            cout << str << endl;
                            targetWork.WcharToChar(codeStr, &str);
                            cout << "编码:\r\n" << str << endl;
                            cout << "编码成功\r\n" << endl;
                        }
                        //释放空间
                        delete[] decoding;
                        delete[] medianValue;
                    }
                    catch (std::exception err) {
                        //释放空间
                        delete[] decoding;
                        delete[] medianValue;
                        cout << err.what() << endl;
                        MessageBoxA(NULL, err.what(), "错误", MB_OK | MB_ICONERROR);
                    }
                }
                break;

            case IDC_CLEAR: //清空按钮
                if (HIWORD(wParam) == BN_CLICKED) { //单击按钮
                    SetDlgItemText(hWnd, IDC_DECOING, TEXT(""));
                    SetDlgItemText(hWnd, IDC_MEDIAN_VALUE, TEXT(""));
                    SetDlgItemText(hWnd, IDC_CODE, TEXT(""));
                }
                break;

            default:
                return DefWindowProc(hWnd, message, wParam, lParam);
            }
        }
        break;

    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);
            // TODO: 在此处添加使用 hdc 的任何绘图代码...
            EndPaint(hWnd, &ps);
        }
        break;

    case WM_DESTROY:
        PostQuitMessage(0);
        break;

    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

//控件子窗口
LRESULT CALLBACK ChildProc(HWND hWndChild, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
    switch (uMsg)
    {
    case WM_KEYDOWN:
        if (GetDlgCtrlID(hWndChild) != IDC_PROGRESS && GetDlgCtrlID(hWndChild) != IDC_STARTCODE && GetDlgCtrlID(hWndChild) != IDC_CLEAR && wParam == 0x41 && GetKeyState(VK_CONTROL) < 0) {
            SendMessage(hWndChild, EM_SETSEL, 0, -1);
        }
        break;

    default:
        break;
    }

    // 其他消息传递给默认窗口过程
    return DefSubclassProc(hWndChild, uMsg, wParam, lParam);
} 

// “关于”和进度框的消息处理程序。
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);
    switch (message)
    {
    case WM_INITDIALOG:
        return (INT_PTR)TRUE;

    case WM_COMMAND:
        if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
        {
            EndDialog(hDlg, LOWORD(wParam));
            return (INT_PTR)TRUE;
        }
        break;
    }
    return (INT_PTR)FALSE;
}
